package com.wj.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hospital.common.pojo.AuditResult;
import com.wj.service.ImageAuditService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

@Service
public class ImageAuditServiceImpl implements ImageAuditService {

    @Value("${chatbot.system-prompt}")
    private String systemPrompt;

    @Value("${spring.ai.dashscope.api-key}")
    private String dashscopeApiKey;

    private Integer lastError = AuditResult.ERROR_API_REQUEST;
    @Override
    public String auditByUrl(String imageUrl) {
        try {
            // 验证API密钥
            if (dashscopeApiKey == null || dashscopeApiKey.isEmpty()) {
                return "错误: DashScope API密钥未配置";
            }

            // 验证图片URL
            if (imageUrl == null || imageUrl.isEmpty()) {
                return "错误: 图片URL不能为空";
            }

            // 1. 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + dashscopeApiKey);
            // 注意：不再需要 X-DashScope-SSE 头，因为禁用了流式响应

            // 2. 构建正确的请求结构
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", "qwen3-vl-plus");

            // 创建input结构
            Map<String, Object> input = new HashMap<>();

            // 创建messages结构
            List<Map<String, Object>> messages = new ArrayList<>();
            Map<String, Object> userMessage = new HashMap<>();
            userMessage.put("role", "user");

            // 创建content数组 - 必须同时包含文本和图片
            List<Object> contentList = new ArrayList<>();

            // 文本内容
            Map<String, String> textContent = new HashMap<>();
            textContent.put("text", systemPrompt);
            contentList.add(textContent);

            // 图片内容
            Map<String, String> imageContent = new HashMap<>();
            imageContent.put("image", imageUrl);
            contentList.add(imageContent);

            userMessage.put("content", contentList);
            messages.add(userMessage);
            input.put("messages", messages);

            // 将input放入请求体
            requestBody.put("input", input);

            // 关键：禁用流式响应，确保只返回单条结果
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("stream", false);
            requestBody.put("parameters", parameters);

            // 3. 转换为JSON
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonBody = objectMapper.writeValueAsString(requestBody);

            // 4. 发送请求
            RestTemplate restTemplate = new RestTemplate();
            HttpEntity<String> request = new HttpEntity<>(jsonBody, headers);

            ResponseEntity<String> responseEntity = restTemplate.postForEntity(
                    "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation",
                    request,
                    String.class
            );

            // 检查HTTP状态
            if (responseEntity.getStatusCode() != HttpStatus.OK) {
                return "API请求失败: " + responseEntity.getStatusCodeValue() +
                        "，响应: " + responseEntity.getBody();
            }

            // 5. 解析响应并提取审核结果
            String responseBody = responseEntity.getBody();
            JsonNode rootNode = objectMapper.readTree(responseBody);

            // 从响应中提取AI的回复文本
            JsonNode contentNode = rootNode
                    .path("output")
                    .path("choices")
                    .get(0)
                    .path("message")
                    .path("content")
                    .get(0)
                    .path("text");

            if (contentNode.isMissingNode() || contentNode.isNull()) {
                return "错误: 无法解析API响应内容";
            }

            String aiResponse = contentNode.asText().trim();

            // 6. 标准化输出结果
            if ("1".equals(aiResponse)) {
                return "1";  // 合规
            } else if (aiResponse.startsWith("不合规:")) {
                return aiResponse;  // 不合规及原因
            } else {
                // 如果AI没有按要求格式返回，进行清理
                if (aiResponse.contains("合规")) {
                    return "1";
                } else {
                    // 提取不合规原因（如果有的话）
                    int idx = aiResponse.indexOf("不合规:");
                    if (idx >= 0) {
                        return aiResponse.substring(idx);
                    }
                    return "不合规: 无法识别的违规内容";
                }
            }

        } catch (JsonProcessingException e) {
            return "JSON处理错误: " + e.getMessage();
        } catch (Exception e) {
            return "请求错误: " + e.getMessage() + "，发送的JSON: " + getRequestBodyDebug(imageUrl);
        }
    }
    /**
     * 通过Base64编码的图片进行审核
     */
    public Integer auditByBase64(String base64Image, String woundType) {
        try {
            // 1. 验证Base64格式
            if (base64Image == null || !base64Image.startsWith("data:image/")) {
                System.out.println("无效的Base64图片格式");
                return AuditResult.ERROR_IMAGE_URL;
            }

            // 2. 医疗上下文验证（使用woundType作为上下文）
            if (woundType == null || woundType.isEmpty()) {
                System.out.println("缺少伤口类型信息");
                // 仍允许审核，但记录警告
            }

            // 3. 验证API密钥
            if (dashscopeApiKey == null || dashscopeApiKey.isEmpty()) {
                System.out.println("API密钥未配置");
                return AuditResult.ERROR_API_KEY;
            }

            // 4. 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + dashscopeApiKey);

            // 5. 构建医疗专用请求结构
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", "qwen3-vl-plus");

            Map<String, Object> input = new HashMap<>();
            List<Map<String, Object>> messages = new ArrayList<>();

            Map<String, Object> userMessage = new HashMap<>();
            userMessage.put("role", "user");

            List<Object> contentList = new ArrayList<>();

            // 构建更精确的医疗提示词（包含伤口类型）
            String contextPrompt = systemPrompt;
            Map<String, String> textContent = new HashMap<>();
            textContent.put("text", contextPrompt);
            contentList.add(textContent);

            // Base64图片内容（关键：使用Base64代替URL）
            Map<String, String> imageContent = new HashMap<>();
            imageContent.put("image", base64Image);
            contentList.add(imageContent);

            userMessage.put("content", contentList);
            messages.add(userMessage);
            input.put("messages", messages);
            requestBody.put("input", input);

            // 禁用流式响应
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("stream", false);
            parameters.put("sensitive_level", 1);
            requestBody.put("parameters", parameters);

            // 6. 发送请求
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonBody = objectMapper.writeValueAsString(requestBody);

            RestTemplate restTemplate = new RestTemplate();
            HttpEntity<String> request = new HttpEntity<>(jsonBody, headers);

            ResponseEntity<String> responseEntity = restTemplate.postForEntity(
                    "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation",
                    request,
                    String.class
            );

            // 7. 处理响应（与auditByUrl相同）
            Integer integer = processAuditResponse(responseEntity, base64Image);
            System.out.println("integer = " + integer);
            return integer;

        } catch (HttpClientErrorException.BadRequest e) {
            // ✅ 捕获400 Bad Request
            handleBadRequest(e);
            return lastError;
        } catch (HttpClientErrorException e) {
            // 处理其他HTTP错误
            System.out.println("HTTP错误: " + e.getStatusCode() + " - " + e.getMessage());

        } catch (Exception e) {
            System.out.println("请求错误: " + e.getMessage());
        }

        // 默认返回通用错误
        return AuditResult.ERROR_API_REQUEST;
    }

    /**
     * 处理400 Bad Request异常
     */
    private void handleBadRequest(HttpClientErrorException.BadRequest e) {
        String responseBody = e.getResponseBodyAsString();

        if (responseBody != null) {
            // 检查是否为DataInspectionFailed
            if (responseBody.contains("DataInspectionFailed")) {
                System.out.println("外层安全检查拦截: " + responseBody);

                // 🔥 关键：这里应该设置一个标志，让调用方知道是安全拦截
                lastError = AuditResult.ERROR_SECURITY_BLOCK;
                return;
            }

            // 检查是否为参数错误
            if (responseBody.contains("InvalidParameter")) {
                System.out.println("参数错误: " + responseBody);
            }
        }

        System.out.println("其他400错误: " + e.getMessage());
        lastError = AuditResult.ERROR_API_REQUEST;
    }
    /**
     * 新增：直接通过MultipartFile进行审核（与您现有接口兼容）
     */
    @Override
    public Integer auditByMultipartFile(MultipartFile file) {
        try {
            // 1. 获取内容类型
            String contentType = file.getContentType();
            System.out.println("contentType = " + contentType);
            if (contentType == null) {
                return AuditResult.ERROR_IMAGE_URL;
            }

            // 2. 判断是否为图片类型
            if (isImageType(contentType)) {
                // 原有图片处理流程不变
                return handleImageFile(file);
            }

            // 3. 处理非图片媒体（视频、音频等）
            else if (isVideoOrAudioType(contentType)) {
                return handleVideoOrAudioFile(file);
            }

            else {
                // 不支持的类型
                return AuditResult.ERROR_IMAGE_URL;
            }

        } catch (IOException e) {
            return AuditResult.ERROR_IMAGE_URL;
        }
    }
    private boolean isImageType(String contentType) {
        return "image/jpeg".equals(contentType) ||
                "image/png".equals(contentType) ||
                "image/jpg".equals(contentType) ||
                "image/webp".equals(contentType) ||
                "image/gif".equals(contentType) ||
                "image/bmp".equals(contentType) ||
                "image/svg+xml".equals(contentType);
    }

    private boolean isVideoOrAudioType(String contentType) {
        return contentType.startsWith("text/") ||
                "application/msword".equals(contentType) ||
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document".equals(contentType) ||
                "application/vnd.ms-powerpoint".equals(contentType) ||
                "application/vnd.openxmlformats-officedocument.presentationml.presentation".equals(contentType) ||
                "application/pdf".equals(contentType) ||
                "application/vnd.ms-excel".equals(contentType) ||
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equals(contentType);
    }

    // 单独处理图片（复用原有逻辑）
    private Integer handleImageFile(MultipartFile file) throws IOException {
        if (file.getSize() > 5 * 1024 * 1024) { // 5MB限制
            return AuditResult.ERROR_IMAGE_URL;
        }
        String base64Image = convertToBase64(file);
        return auditByBase64(base64Image, systemPrompt); // 继续走AI审核
    }

    // 处理视频或音频：只做基础安全校验
    private Integer handleVideoOrAudioFile(MultipartFile file) {
        // 示例规则：可以加更多业务逻辑

        // 文件大小限制（例如 50MB）
        if (file.getSize() > 50 * 1024 * 1024) {
            System.out.println("视频/音频文件过大: " + file.getSize());
            return AuditResult.ERROR_IMAGE_URL;
        }

        // 检查文件扩展名黑名单（防止 .exe, .php 等伪装）
        String originalFilename = file.getOriginalFilename().toLowerCase();
        if (originalFilename.contains(".php") ||
                originalFilename.contains(".jsp") ||
                originalFilename.contains(".exe") ||
                originalFilename.contains(".bat")) {
            System.out.println("发现可疑文件扩展名: " + originalFilename);
            return AuditResult.NON_COMPLIANT; // 或 ERROR_IMAGE_URL
        }

        // ✅ 默认认为合法 —— 医疗场景下的视频也接受（如换药过程录像）
        // 如果你要更严格，可集成 FFmpeg 提取帧送 AI 审核（复杂，不推荐轻量级使用）

        return AuditResult.COMPLIANT;
    }

    // 辅助方法
    private boolean isAllowedImageType(String contentType) {
        return "image/jpeg".equals(contentType) ||
                "image/png".equals(contentType) ||
                "image/jpg".equals(contentType);
    }

    private String convertToBase64(MultipartFile file) throws IOException {
        return "data:" + file.getContentType() +
                ";base64," +
                Base64.getEncoder().encodeToString(file.getBytes());
    }

    /**
     * 构建包含伤口类型的医疗提示词
     */
    private String buildMedicalPrompt(String woundType) {
        StringBuilder prompt = new StringBuilder();
        prompt.append("你是一个医院远程诊疗系统的专业医疗内容审核员。\n\n");

        prompt.append("当前审核上下文:\n");
//        if (woundType != null && !woundType.isEmpty()) {
//            prompt.append("- 伤口类型: ").append(convertWoundTypeToText(woundType)).append("\n");
//        }
        prompt.append("- 这是正规医疗机构的内部系统\n");
        prompt.append("- 所有图片仅限医疗专业人员访问\n\n");

        prompt.append("允许的医疗内容（不视为违规）:\n");
        prompt.append("• 各类伤口照片，无论出血量大小\n");
        prompt.append("• 手术过程中的组织暴露图像\n");
        prompt.append("• 有明显医疗环境的创伤处理过程\n\n");

        prompt.append("需标记为违规的内容:\n");
        prompt.append("• 与医疗无关的暴力场景\n");
        prompt.append("• 故意自残的非治疗性图片\n");
        prompt.append("• 非医疗环境下的伤口展示\n");
        prompt.append("• 包含患者面部且无遮挡的图片\n");
        prompt.append("• 任何色情、政治敏感或违法内容\n\n");

        prompt.append("重要规则:\n");
        prompt.append("1. 所有医疗场景下的伤口和出血图片均视为合规\n");
        prompt.append("2. 仅当内容明显与医疗无关或违反医疗隐私规范时才标记为不合规\n");
        prompt.append("3. 合规图片只返回\"1\"，不合规返回\"不合规: [具体原因]\"");

        return prompt.toString();
    }

//    private String convertWoundTypeToText(String woundType) {
//        switch (woundType) {
//            case "cut": return "切割伤";
//            case "burn": return "烧伤";
//            case "abrasion": return "擦伤";
//            case "surgical": return "术后伤口";
//            case "ulcer": return "溃疡";
//            default: return "未知类型伤口";
//        }
//    }

    /**
     * 处理API响应（可被auditByUrl和auditByBase64共享）
     */
    private Integer processAuditResponse(ResponseEntity<String> responseEntity, String imageRef) {
        // 与之前auditByUrl中的响应处理逻辑相同
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            String responseBody = responseEntity.getBody();

            // 特殊处理医疗图片的400错误
            if (responseBody != null && responseBody.contains("DataInspectionFailed")) {
                System.out.println("医疗图片被安全检查拦截: " + imageRef);
                // 医疗图片即使被安全检查拦截也视为合规
                return AuditResult.COMPLIANT;
            }

            System.out.println("API请求失败: " + responseEntity.getStatusCodeValue() +
                    "，响应: " + responseBody);
            return AuditResult.ERROR_API_REQUEST;
        }

        // 提取和处理AI响应（与之前相同）
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            String responseBody = responseEntity.getBody();
            JsonNode rootNode = objectMapper.readTree(responseBody);

            JsonNode contentNode = rootNode
                    .path("output")
                    .path("choices")
                    .get(0)
                    .path("message")
                    .path("content")
                    .get(0)
                    .path("text");

            if (contentNode.isMissingNode() || contentNode.isNull()) {
                System.out.println("无法解析API响应内容");
                return AuditResult.ERROR_RESPONSE_PARSE;
            }

            String aiResponse = contentNode.asText().trim();

            // 医疗场景专用后处理
            if (aiResponse.startsWith("0:")) {
                String reason = aiResponse.substring(5).trim().toLowerCase();

                // 检查是否是伤口/出血被误判为暴力
//                if ((reason.contains("暴力") || reason.contains("伤口") ||
//                        reason.contains("出血") || reason.contains("血"))) {
//
//                    System.out.println("医疗伤口图片被误判: " + imageRef + " - 原因: " + reason);
//                    return AuditResult.COMPLIANT;
//                }

                return AuditResult.NON_COMPLIANT;
            }

            return "1".equals(aiResponse.trim()) ? AuditResult.COMPLIANT : AuditResult.COMPLIANT;

        } catch (Exception e) {
            System.out.println("响应处理错误: " + e.getMessage());
            return AuditResult.ERROR_RESPONSE_PARSE;
        }
    }

    // 调试用：生成调试信息
    private String getRequestBodyDebug(String imageUrl) {
        try {
            Map<String, Object> debugBody = new HashMap<>();
            debugBody.put("model", "qwen3-vl-plus");

            Map<String, Object> input = new HashMap<>();
            List<Map<String, Object>> messages = new ArrayList<>();

            Map<String, Object> userMsg = new HashMap<>();
            userMsg.put("role", "user");

            List<Object> contentList = new ArrayList<>();
            // 添加文本内容
            Map<String, String> textContent = new HashMap<>();
            textContent.put("text", systemPrompt);
            contentList.add(textContent);
            // 添加图片内容
            Map<String, String> imageContent = new HashMap<>();
            imageContent.put("image", imageUrl);
            contentList.add(imageContent);

            userMsg.put("content", contentList);
            messages.add(userMsg);
            input.put("messages", messages);

            debugBody.put("input", input);

            // 添加禁用流式响应的参数
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("stream", false);
            debugBody.put("parameters", parameters);

            return new ObjectMapper().writeValueAsString(debugBody);
        } catch (Exception e) {
            return "调试信息生成失败: " + e.getMessage();
        }
    }
}
